Skip to content

[Profile] Add guest profile sign-in flow - #116

Open
conniecliu wants to merge 2 commits into
mainfrom
Connie/SkipLoginFlow
Open

conniecliu wants to merge 2 commits into
mainfrom
Connie/SkipLoginFlow

Conversation

@conniecliu

@conniecliu conniecliu commented Sep 16, 2026

Copy link
Copy Markdown

Overview

This implements the skip sign-in flow for when a user skips the sign-in prompt. Changes include:

  • New guest profile screen that appears when a user is not logged in.
  • Replaced main logo PNG with XML for visual clarity.
  • Modified buttons and navigation for new flow and UI.

Details on the flow and UI can be found in this Figma.

Changes Made

  • Added a GuestProfileScreen that appears only if the user skipped the sign-in prompt during early onboarding.
  • Modified existing buttons to accommodate the new UI for the GuestProfileScreen
  • Replaced the main logo with an XML instead of a PNG.
  • Added a new XML file for the goals logo specifically for the guest profile.
  • Modified MainNavigationWrapper and RootNavigationViewModel to prevent the user from backing back into the onboarding flow after onboarding is completed + direct them to login if they haven't already + be directed to Home.

Test Coverage

  • Tested on my Google Pixel 9a.

Screenrecording

Summary by CodeRabbit

  • New Features
    • Added a dedicated guest profile screen for signed-out users, including benefits, branding, and a Google sign-in option.
    • Added new profile and goal visuals.
  • Bug Fixes
    • Improved navigation after onboarding, skipping intermediate screens when returning to Home.
    • Ensured the correct profile experience appears based on sign-in status.
  • UI Improvements
    • Improved button layout consistency.
    • Enabled flexible placement of the sign-in button.

This implements the skip sign-in flow for when a user skips the sign-in
prompt. Changes include:
- New guest profile screen that appears when a user is not logged in.
- Replaced main logo png with xml for visual clarity.
- Modified buttons and navigation for new flow and UI.
@coderabbitai

coderabbitai Bot commented Sep 16, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 8a7be1a4-5bc5-4367-a06a-d0c6e348ebb0

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 49eab4d1-adf9-4bc1-88f4-51801b31224a

📥 Commits

Reviewing files that changed from the base of the PR and between 6ec2e24 and 0efb064.

⛔ Files ignored due to path filters (1)
  • app/src/main/res/drawable/ic_main_logo.png is excluded by !**/*.png
📒 Files selected for processing (7)
  • app/src/main/java/com/cornellappdev/uplift/ui/MainNavigationWrapper.kt
  • app/src/main/java/com/cornellappdev/uplift/ui/components/general/UpliftButton.kt
  • app/src/main/java/com/cornellappdev/uplift/ui/components/onboarding/auth/LogInButton.kt
  • app/src/main/java/com/cornellappdev/uplift/ui/screens/profile/GuestProfileScreen.kt
  • app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/nav/RootNavigationViewModel.kt
  • app/src/main/res/drawable/guest_profile_goal.xml
  • app/src/main/res/drawable/ic_main_logo.xml

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The PR adds a guest profile screen with Google sign-in, updates sign-in button modifiers, adds supporting icons, and changes root navigation to select guest content and clear onboarding routes when navigating Home.

Changes

Guest profile navigation

Layer / File(s) Summary
Guest profile UI and sign-in entry
app/src/main/java/com/cornellappdev/uplift/ui/screens/profile/GuestProfileScreen.kt, app/src/main/java/com/cornellappdev/uplift/ui/components/onboarding/auth/LogInButton.kt, app/src/main/java/com/cornellappdev/uplift/ui/components/general/UpliftButton.kt, app/src/main/res/drawable/*
Adds the guest profile layout, benefit rows, logo, goal icon, and Google sign-in callback. LogInButton accepts and applies a Modifier. UpliftButton uses a fresh modifier for its text.
Session-derived navigation state
app/src/main/java/com/cornellappdev/uplift/ui/viewmodels/nav/RootNavigationViewModel.kt
Adds withSession to update session state and emit navigation events when the route or login state changes.
Profile route and back-stack navigation
app/src/main/java/com/cornellappdev/uplift/ui/MainNavigationWrapper.kt
Renders GuestProfileScreen for logged-out users. Home navigation uses popUpTo(0) and launchSingleTop = true.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant RootNavigationViewModel
  participant MainNavigationWrapper
  participant GuestProfileScreen
  participant LoginViewModel
  RootNavigationViewModel->>MainNavigationWrapper: emit session navigation event
  MainNavigationWrapper->>GuestProfileScreen: render guest profile
  GuestProfileScreen->>LoginViewModel: invoke Google sign-in
Loading

Merge Risk: ⚪ Minimal · up to 0efb0

No concrete merge-blocking risk remains in the guest profile and navigation changes.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 5 files. (2 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding a guest profile sign-in flow.
Description check ✅ Passed The description includes the required Overview, Changes Made, and Test Coverage sections. It explains the guest profile flow, navigation updates, assets, and device testing. The description does not u…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 5 files. (2 skipped: 2 unsupported.)

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch Connie/SkipLoginFlow

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@caleb-bit caleb-bit left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the demo, there is a delay when the profile page is loaded, which I'm guessing is just the components waiting on the async data, but to the user this looks like a weird flicker. Do we have loading state designs for the profile page? If we don't, you can just add that as a Github issue and rerequest review. If we do, I think it's correct to implement it in this PR so the UI displayed is correct.

- Share shimmer placeholders between Home and Profile
- Crossfade profile loading, error/retry, and loaded content
- Initialize profile as loading to prevent empty-content flashes
- Resolve the saved skip-login preference before showing the first screen
@conniecliu

conniecliu commented Sep 22, 2026

Copy link
Copy Markdown
Author

Problems

  • ProfileScreen always displayed its content even while the profile request was in progress, causing the "flicker" users see.
  • Noticed that if a user skips login, opens the guest profile tab, then restarts the app and reopens it, they would see the sign-in prompt screen briefly before the home screen, which was buggy and not the correct UX.

Changes/Fixes

Profile screen flicker

  • Factored out a shared Surface into a LoadingPlaceholder composable since the loading design for profiles should be the same as the one for HomeScreen aka MainLoading.
  • Implemented ProfileLoading, a profile-specific skeleton for the loading state that shimmers while loading.
  • ProfileScreen: accepts the shimmer, selects between loading/error/loaded content states, and crossfades depending on that state.
  • ProfileViewModel: instantiate loading = true to avoid an empty frame

Returning guest startup flicker

  • The main root cause was that RootNavigationViewModel selected onboarding for a signed-out user without considering the skip preference.
  • RootNavigationViewModel: added flag isStartupReady so that it is true when the destination has been resolved after reading the skip preference.
  • MainNavigationWrapper: shows a white background and returns before creating the nav controller or consuming nav events while startup is unresolved. This was done since the original wrapper has already created its NavHost with onboarding.

Testing

  • Google Pixel 9a

Recordings

Updated demo (with the profile screen fix)

Click here.

Demo of restarting the app and re-opening as a guest

Click here.

@caleb-bit caleb-bit left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Thanks for fixing the flicker bug. I mostly just left nits, but there is a change to ProfileUiState that is worth considering as well as another loading state change.


@Composable
fun LogInButton(onRequestResult: (Credential) -> Unit) {
fun LogInButton(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very minor unrelated nit: I think LoginButton is more correct.

)
}

// TODO: Try to move parts that don't require Context to viewmodel

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't have to be in this PR, but this TODO should definitely be done. Business logic inside a component file is pretty unexpected. Feel free to add a Github issue or make a stacked PR for this.

// Wait for the saved skip-login preference before creating the graph or consuming navigation
// events. Otherwise a returning guest briefly sees Onboarding before being sent to Home.
if (!rootNavigationUiState.isStartupReady) {
Box(Modifier.fillMaxSize().background(Color.White))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I don't think we should be defaulting to a completely white screen for anything. Can we keep it on the splash screen until it loads? I don't have too much experience with splash screen API, but try using this reference.

) {
data class RootNavigationUiState(
val isLoggedIn: Boolean = false,
// The initial destination is temporary until the saved skip preference has been read.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this comment is that useful here.

)
) {
// Determines the guest-to-authenticated transition
internal fun withSession(loggedIn: Boolean, destination: UpliftRootRoute): RootNavigationUiState {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename this? withSession is not too informative.

Crossfade(
targetState = contentState,
modifier = Modifier.fillMaxSize().padding(innerPadding),
label = "Profile"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: extract strings into strings.xml.

when (state) {
ProfileContentState.Loading -> ProfileLoading(loadingShimmer)
// Reuse the existing retry UI so a failed request does not look like an empty profile.
ProfileContentState.Error -> MainError(reload = onRetry)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: here, onRetry is presumably a lambda, whereas reload sounds like it could be a boolean flag. onReload would make this make more sense.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preview would be helpful

@Preview(showBackground = true, widthDp = 393, heightDp = 769)
@Composable
private fun GuestProfilePreview() {
GuestProfileScreenContent {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preview should use theme (UpliftTheme)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Extract strings

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants